package com.weixing.mall.provider.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.utils.EnumUtil;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.enums.IsEnableEnum;
import com.weixing.mall.provider.api.model.CalcProfitPo;
import com.weixing.mall.provider.api.model.enums.ActTypeEnum;
import com.weixing.mall.provider.api.model.enums.AgentLevelEnum;
import com.weixing.mall.provider.api.model.enums.AgentTypeEnum;
import com.weixing.mall.provider.api.model.enums.OrderTypeEnum;
import com.weixing.mall.provider.api.model.vo.*;
import com.weixing.mall.provider.api.service.ActivityRpcService;
import com.weixing.mall.provider.api.service.AgentServiceRpc;
import com.weixing.mall.provider.model.domain.Order;
import com.weixing.mall.provider.model.domain.OrderAgent;
import com.weixing.mall.provider.model.enums.OrderFromEnum;
import com.weixing.mall.provider.util.OrderUtil;
import com.weixing.mall.util.number.MoneyUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/**
 * 处理跟代理商相关的一些公共业务逻辑，manager的语义可能不够准确，暂时先这么用
 *
 * @author  Small
 * @date  2020/5/16 17:49
 * @since  1.0
 **/
@Component("profitManager")
public class ProfitManager {


    private static final int AGENT = 2;
    private static final int COMPANY = 1;

    @Autowired
    private AgentServiceRpc agentServiceRpc;
    @Autowired
    private ActivityRpcService activityRpcService;


    /**
     * 订单获利计算
     *
     * @param order         订单
     * @param agentRpcVo    代理
     * @param rebateRuleId  折扣规则id
     * @return
     */
    public List<OrderAgent> calcProfit(Order order, AgentRpcVo agentRpcVo, Long rebateRuleId) {
        if (null != agentRpcVo) {
            return calcProfitOfBindAgentOrder(order, agentRpcVo, rebateRuleId);
        } else if (null != order.getCustomerId()) {
            List<OrderAgent> list = Lists.newArrayList();
            list.add(getAgentOrder(order, null));
            return list;
        }
        return null;
    }


    /**
     * 下单计算代理获利
     *
     * @param order
     * @param agentRpcVo
     * @param rebateRuleId
     * @return
     */
    public List<OrderAgent> calcProfitOfBindAgentOrder(Order order, AgentRpcVo agentRpcVo, Long rebateRuleId) {
        List<OrderAgent> list = Lists.newArrayList();
        OrderTypeEnum orderType = EnumUtil.getIEnum(OrderTypeEnum.class, order.getOrderType());
        switch (orderType) {
            case NORMAL:
                list = calcNormal(order, agentRpcVo);
                break;
            case AGENT:
                list = calcAgentAct(order, agentRpcVo, rebateRuleId);
                break;
            case SECKILL:
                list = calcSeckill(order, agentRpcVo, rebateRuleId);
                break;
            default:
                break;
        }
        return list;
    }


    /**
     * 计算分红
     *
     * @param order         订单
     * @param agentRpcVo    代理
     * @param rate          折上折（仅代理商活动）
     * @return 分红
     */
    private List<OrderAgent> calcBonus(Order order, AgentRpcVo agentRpcVo, BigDecimal rate) {
        List<OrderAgent> orderAgents = Lists.newArrayList();
        AgentBonusVo bonusVo = agentRpcVo.getBonusVo();
        AgentBonusVo unnormalBonusVo = agentRpcVo.getUnnormalBonusVo();
        Result<AgentBonusRuleVo> agentBonusRuleVoResult = agentServiceRpc.selectBonusRule(order.getOrderType());
        if (!agentBonusRuleVoResult.isSuccess()) {
            throw new BusinessException(agentBonusRuleVoResult.getMsg());
        }
        AgentBonusRuleVo bonusRule = agentBonusRuleVoResult.getData();
        BigDecimal rate1st = reCalcRate(bonusRule.getFirstLevelRadio(), rate);
        BigDecimal rate2nd = reCalcRate(bonusRule.getSecondLevelRadio(), rate);
        // 如果二级分红人为0，说明只有一级分红关系
        if (IsEnableEnum.DISABLE.getValue().equals(bonusVo.getIsLv2enable())) {
            if (IsEnableEnum.ENABLE.getValue().equals(bonusVo.getIsLv1enable())) {
                // 晋升为一级代理时取 分红一级比例(晋升为一级代理)
                if (AgentLevelEnum.LEVEL_1.getValue().equals(bonusVo.getPromoteFirstLevel())) {
                    rate1st = reCalcRate(bonusRule.getFirstLevelLv1Radio(), rate);
                }
                orderAgents.add(getAgentOrder(order, getAgent(bonusVo.getObligeeId1st()),
                        getBonusProfit(order.getOrderPrice(), rate1st),
                        rate1st, rate1st, GlobalConstant.BONUS_LEVEL1, bonusVo));
            }
        } else {
            orderAgents.add(getAgentOrder(order, getAgent(bonusVo.getObligeeId1st()),
                    getBonusProfit(order.getOrderPrice(), rate2nd), rate2nd,
                    rate1st, GlobalConstant.BONUS_LEVEL1, bonusVo));
            orderAgents.add(getAgentOrder(order, getAgent(bonusVo.getObligeeId2nd()),
                    getBonusProfit(order.getOrderPrice(), rate2nd), rate2nd,
                    rate1st, GlobalConstant.BONUS_LEVEL2, bonusVo));
        }

        // 处理3个平一级的分红关系
        if (null != unnormalBonusVo && IsEnableEnum.ENABLE.getValue().equals(unnormalBonusVo.getIsEnable())){
//            BigDecimal rateUnnormal = reCalcRate(bonusRule.getUnnormalBonusRadio(), rate);
            BigDecimal rateUnnormal = bonusRule.getUnnormalBonusRadio();
            orderAgents.add(getAgentOrder(order, getAgent(unnormalBonusVo.getObligeeId1st()),
                    getBonusProfit(order.getOrderPrice(), rateUnnormal), rateUnnormal,
                    rateUnnormal, GlobalConstant.BONUS_LEVEL1, unnormalBonusVo));
        }

        return orderAgents;
    }

    private BigDecimal reCalcRate(BigDecimal srcRate, BigDecimal rate) {
        return null == rate ? srcRate : NumberUtil.mul(srcRate, rate);
    }

    private AgentRpcVo getAgent(Long agentId) {
        Result<AgentRpcVo> agentRpcVoResult = agentServiceRpc.selectByAgentId(agentId);
        if (!agentRpcVoResult.isSuccess()) {
            throw new BusinessException(agentRpcVoResult.getMsg());
        }
        return agentRpcVoResult.getData();
    }

    /**
     * 二级分红比例
     *
     * @param orderPrice      订单金额
     * @param rate            分红比例
     * @return 分红
     */
    private BigDecimal getBonusProfit(BigDecimal orderPrice, BigDecimal rate) {
        return NumberUtil.round(NumberUtil.mul(orderPrice, rate), 2, RoundingMode.HALF_UP);
    }

    /**
     * 秒杀活动
     *
     * @param order             订单
     * @param agentRpcVo        代理
     * @param rebateRuleId      秒杀分红规则
     * @return 代理获利
     */
    private List<OrderAgent> calcSeckill(Order order, AgentRpcVo agentRpcVo, Long rebateRuleId) {

        if (null == rebateRuleId){
            Result<ActRpcVo> actRpcVoResult = activityRpcService.selectById(order.getActId());
            if (!actRpcVoResult.isSuccess()) {
                throw new BusinessException("活动服务不可用，请稍后重试");
            }
            ActRpcVo actRpcVo = actRpcVoResult.getData();
            rebateRuleId = actRpcVo.getRebateRule();
        }

        List<AgentRpcVo> agentTrees = agentRpcVo.getTreeList();
        int ruleCode = getInfoCode(agentTrees);
        Result<AgentRebateRuleInfoVo> ruleInfoVoResult = agentServiceRpc.selectActRebateRule(rebateRuleId, ruleCode);
        if (!ruleInfoVoResult.isSuccess()) {
            throw new BusinessException(ruleInfoVoResult.getMsg());
        }
        AgentRebateRuleInfoVo rebateRuleInfoVo = ruleInfoVoResult.getData();
        // 收益比例
        BigDecimal sumDis = calcSumDiscount(rebateRuleInfoVo);
        // 总收益
        BigDecimal sumProfit = NumberUtil.mul(order.getOrderPrice(), sumDis);
        List<OrderAgent> orderAgents = Lists.newArrayList();
        List<OrderAgent> orderAgentsOfBonus = Lists.newArrayList();
        for (AgentRpcVo po : agentTrees) {
            // 代理对应的折扣
            BigDecimal dis = calcDisCount(rebateRuleInfoVo, po.getAgentLevel(), po.getAgentType());
            // 计算代理对应的收益
            BigDecimal rate = NumberUtil.div(dis, sumDis);
            rate = NumberUtil.round(rate, 2, RoundingMode.HALF_UP);
            BigDecimal profit = NumberUtil.round(NumberUtil.mul(sumProfit, rate), 2, RoundingMode.HALF_UP);
            po.setDiscount(dis);
            orderAgents.add(getAgentOrder(order, po, profit, agentTrees, null, null,null));
            // 计算团队成员的分红
            List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, po, null);
            if (CollUtil.isNotEmpty(orderAgentList)) {
                orderAgentsOfBonus.addAll(orderAgentList);
            }
        }
        // 客服需收款  最后一个就是跟客服有关的
        orderAgents.add(getAgentOrder(order, orderAgents.get(agentTrees.size() - 1)));
        // 分红
        // 代理本人分红计算
        List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, null);
        if (CollUtil.isNotEmpty(orderAgentList)) {
            orderAgentsOfBonus.addAll(orderAgentList);
        }
        if (CollUtil.isNotEmpty(orderAgentsOfBonus)) {
            orderAgents.addAll(orderAgentsOfBonus);
        }
        return orderAgents;
    }

    /**
     * 代理商活动获利计算
     *
     * @param order     订单
     * @param agentRpcVo  代理
     * @return 订单获利
     */
    private List<OrderAgent> calcAgentAct(Order order, AgentRpcVo agentRpcVo, Long discountRule) {

        Result<ActRpcVo> actRpcVoResult = activityRpcService.selectById(order.getActId());
        if (!actRpcVoResult.isSuccess()) {
            throw new BusinessException("活动服务不可用，请稍后重试");
        }
        ActRpcVo actVo = actRpcVoResult.getData();
        // 不传递折扣规则，直接取活动的折扣规则
        discountRule = null == discountRule? actVo.getDiscountRule() : discountRule;
        Result<AgentDiscountVo> agentDiscountVoResult = agentServiceRpc.selectActDiscount(discountRule);
        if (!agentDiscountVoResult.isSuccess()) {
            throw new BusinessException("代理服务不可用，请稍后重试");
        }
        AgentDiscountVo agentDiscountVo = agentDiscountVoResult.getData();
        List<AgentRpcVo> agentTrees = agentRpcVo.getTreeList();
        BigDecimal baseAmount = order.getOrderPrice();
        List<OrderAgent> orderAgents = Lists.newArrayList();
        List<OrderAgent> orderAgentsOfBonus = Lists.newArrayList();
        for (AgentRpcVo po : agentTrees) {
            BigDecimal disCount = calcDisCount(agentDiscountVo, po.getDiscount());
            BigDecimal poAmount = NumberUtil.mul(order.getOrderPrice(), disCount);
            BigDecimal profit = NumberUtil.sub(baseAmount, poAmount);
            baseAmount = poAmount;
            orderAgents.add(getAgentOrder(order, po, profit, agentTrees, disCount, agentDiscountVo,actVo));
            // 计算团队成员的分红
            List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, po, agentDiscountVo.getFactor());
            if (CollUtil.isNotEmpty(orderAgentList)) {
                orderAgentsOfBonus.addAll(orderAgentList);
            }
        }
        // 客服需收款  最后一个就是跟客服有关的
        orderAgents.add(getAgentOrder(order, orderAgents.get(agentTrees.size() - 1)));
        // 分红
        // 代理本人分红计算
        List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, agentDiscountVo.getFactor());
        if (CollUtil.isNotEmpty(orderAgentList)) {
            orderAgentsOfBonus.addAll(orderAgentList);
        }
        if (CollUtil.isNotEmpty(orderAgentsOfBonus)) {
            orderAgents.addAll(orderAgentsOfBonus);
        }
        return orderAgents;
    }


    /**
     * 正价订单获利计算
     *
     * @param order         订单
     * @param agentRpcVo    代理
     * @return 订单获利
     */
    private List<OrderAgent> calcNormal(Order order, AgentRpcVo agentRpcVo) {
        List<AgentRpcVo> agentTrees = agentRpcVo.getTreeList();
        List<OrderAgent> orderAgents = Lists.newArrayList();
        List<OrderAgent> orderAgentsOfBonus = Lists.newArrayList();
        BigDecimal baseAmount = order.getOrderPrice();
        for (AgentRpcVo po : agentTrees) {
            BigDecimal poAmount = NumberUtil.mul(order.getOrderPrice(), po.getDiscount());
            BigDecimal profit = NumberUtil.sub(baseAmount, poAmount);
            baseAmount = poAmount;
            orderAgents.add(getAgentOrder(order, po, profit, agentTrees, null, null,null));
            // 计算团队成员的分红
            // 20210219 计算分红逻辑重构
            List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, po, null);
            if (CollUtil.isNotEmpty(orderAgentList)) {
                orderAgentsOfBonus.addAll(orderAgentList);
            }
        }
        // 客服需收款  最后一个非分红订单就是跟客服有关的
        orderAgents.add(getAgentOrder(order, orderAgents.get(agentTrees.size() - 1)));
        // 代理本人分红计算
        List<OrderAgent> orderAgentList = caleGroupBonus(agentRpcVo, order, null);
        if (CollUtil.isNotEmpty(orderAgentList)) {
            orderAgentsOfBonus.addAll(orderAgentList);
        }
        if (CollUtil.isNotEmpty(orderAgentsOfBonus)) {
            orderAgents.addAll(orderAgentsOfBonus);
        }
        return orderAgents;
    }

    /**
     * 计算团队成员的分红 v2.0
     *
     * @param agentRpcVo 代理结构树
     * @param order 订单
     * @param po 当前代理
     * @param rate 折上折（仅代理活动）
     * @return 分红
     */
    private List<OrderAgent> caleGroupBonus(AgentRpcVo agentRpcVo, Order order, AgentRpcVo po, BigDecimal rate) {
        // 团队分红计算
        List<OrderAgent> orderAgents = null;
        if (null == agentRpcVo.getBonusVo()) {
            Result<AgentRpcVo> agentRpcVoResult = agentServiceRpc.selectByAgentId(po.getId());
            if (agentRpcVoResult.isSuccess()) {
                AgentRpcVo agentData = agentRpcVoResult.getData();
                // 分红关系
                if (null != agentData.getBonusVo()) {
                    orderAgents = calcBonus(order, agentData, rate);
                }
            }
        }
        return orderAgents;
    }

    /**
     * 计算团队成员的分红 v2.0
     *
     * @param agentRpcVo 代理结构树
     * @param order 订单
     * @param rate 折上折（仅代理活动）
     * @return 分红
     */
    private List<OrderAgent> caleGroupBonus(AgentRpcVo agentRpcVo, Order order, BigDecimal rate) {
        // 团队分红计算
        List<OrderAgent> orderAgents = null;
        if (null != agentRpcVo.getBonusVo()) {
            orderAgents = calcBonus(order, agentRpcVo, rate);
        }
        return orderAgents;
    }


    /**
     * 客服记录
     *
     * @param order    订单
     * @param oa       订单利润记录
     * @return         订单利润记录
     */
    private OrderAgent getAgentOrder(Order order, OrderAgent oa) {
        OrderAgent profit = new OrderAgent();
        profit.setAgentProfit(BigDecimal.ZERO);
        profit.setProfitType(GlobalConstant.PROFIT_TYPE_KEFU);
        profit.setIsEnable(OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom()) ? IsEnableEnum.DISABLE.getValue() : IsEnableEnum.ENABLE.getValue());
        // 代理
        profit.setRoleType(1);
        profit.setAgentId(order.getCustomerId());
        profit.setAgentPid(0L);
        profit.setAgentLevel(AgentLevelEnum.KEFU.getValue());
        profit.setAgentName(order.getCustomerName());
        profit.setAgentDiscount(new BigDecimal("1"));
        profit.setKefuId(order.getCustomerId());
        profit.setKefuName(order.getCustomerName());
        if (OrderFromEnum.CUSTOMER.getValue().equals(order.getOrderFrom())) {
            profit.setBelongType(GlobalConstant.PROFIT_BELONG_TYPE_OWN);
        } else if (OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom()) && (null == order.getAgentId() || 0 == order.getAgentId())) {
            profit.setBelongType(GlobalConstant.PROFIT_BELONG_TYPE_OWN);
        } else {
            profit.setBelongType(GlobalConstant.PROFIT_BELONG_TYPE_GROUP);
        }

        profit.setNeedReceive(null == oa ? order.getOrderPrice() : oa.getNeedUppay());
        profit.setPayerId(null == oa ? order.getBuyerId() : oa.getAgentId());
        profit.setPayer(null == oa ? order.getBuyer() : oa.getAgentName());
        profit.setNeedUppay(BigDecimal.ZERO);
        profit.setPayerRole(null == oa ? GlobalConstant.PAYERROLE_MEMBER : GlobalConstant.PAYERROLE_AGENT);
        // 订单
        profit.setOrderId(order.getId());
        profit.setOrderPrice(order.getOrderPrice());
        profit.setOrderType(order.getOrderType());
        profit.setOrderFrom(order.getOrderFrom());
        profit.setRemark("");
        profit.setOrderSn(order.getOrderSn());
        return profit;
    }


    /**
     * 代理记录
     *
     * @param order    订单
     * @param agent    代理商
     * @param profitAmount
     * @param agentTrees  代理结构树
     * @param discount   折扣
     * @param agentDiscountVo  代理商活动折扣
     * @param actVo  活动
     * @return OrderAgent
     */
    private OrderAgent getAgentOrder(Order order,
                                     AgentRpcVo agent,
                                     BigDecimal profitAmount,
                                     List<AgentRpcVo> agentTrees,
                                     BigDecimal discount,
                                     AgentDiscountVo agentDiscountVo,
                                     ActRpcVo actVo) {
        OrderAgent profit = new OrderAgent();
        profit.setAgentProfit(profitAmount);
        profit.setProfitType(getProfitType(order.getOrderFrom()));
        profit.setIsEnable(OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom()) ? IsEnableEnum.DISABLE.getValue() : IsEnableEnum.ENABLE.getValue());
        // 代理
        profit.setRoleType(2);
        profit.setAgentId(agent.getId());
        profit.setAgentLevel(agent.getAgentLevel());
        profit.setAgentSn(agent.getAgentSn());
        profit.setAgentName(agent.getAgentName());
        profit.setAgentMobile(agent.getMobile());
        profit.setAgentDiscount(null == discount ? agent.getDiscount() : discount);
        profit.setKefuId(agent.getCustomerId());
        profit.setKefuName(agent.getCustomerName());
        profit.setAgentType(agent.getAgentType());
        profit.setAgentPid(agent.getParentId());
        // 父级折扣
        CalcProfitPo parseParent = parseParent(agent.getId(), agent.getAgentTreePath());
        profit.setAgentPdiscount(null == parseParent ? BigDecimal.ZERO : parseParent.getDiscount());
        profit.setBelongType(getBelongType(order.getAgentId().longValue(), agent.getId().longValue()));
        Map<String, Object> result = calcUpAndReceive(order, agent, agentTrees, agentDiscountVo,actVo);
        profit.setNeedReceive((BigDecimal) result.get("needReceive"));
        profit.setNeedUppay((BigDecimal) result.get("needUppay"));
        profit.setPayerId((Long) result.get("payerId"));
        profit.setPayerRole((Integer) result.get("payerRole"));
        profit.setReceivorId((Long) result.get("receivorId"));
        profit.setReceivorRole((Integer) result.get("receivorRole"));
        profit.setPayer((String) result.get("payer"));
        profit.setReceivor((String) result.get("receivor"));
        // 订单
        profit.setOrderId(order.getId());
        profit.setOrderPrice(order.getOrderPrice());
        profit.setOrderType(order.getOrderType());
        profit.setOrderFrom(order.getOrderFrom());
        profit.setRemark("");
        profit.setOrderSn(order.getOrderSn());
        return profit;
    }

    /**
     * 分红
     * @param order      订单
     * @param agent      分红团队（获得分红的代理）
     * @param profitAmount   分红金额
     * @param rate         分红比例（当前）
     * @param rete1         一级分红比例
     * @param bonusType    分红等级（1级分红/二级分红）
     * @param bonusVo      分红团队记录
     * @return 分红
     */
    private OrderAgent getAgentOrder(Order order, AgentRpcVo agent, BigDecimal profitAmount, BigDecimal rate, BigDecimal rete1, int bonusType, AgentBonusVo bonusVo) {
        OrderAgent profit = new OrderAgent();
        profit.setAgentProfit(profitAmount);
        profit.setProfitType(GlobalConstant.PROFIT_TYPE_BONUS);
        // 代理
        profit.setAgentId(agent.getId());
        profit.setAgentLevel(agent.getAgentLevel());
        profit.setAgentSn(agent.getAgentSn());
        profit.setAgentDiscount(agent.getDiscount());
        profit.setBelongType(GlobalConstant.PROFIT_BELONG_TYPE_PARTNER);
        profit.setAgentName(agent.getAgentName());
        profit.setAgentMobile(agent.getMobile());
        profit.setAgentDiscount(agent.getDiscount());
        profit.setKefuId(agent.getCustomerId());
        profit.setKefuName(agent.getCustomerName());
        profit.setAgentType(agent.getAgentType());
        profit.setAgentPid(agent.getParentId());
        // 订单
        profit.setOrderId(order.getId());
        profit.setOrderPrice(order.getOrderPrice());
        profit.setOrderType(order.getOrderType());
        profit.setOrderFrom(order.getOrderFrom());
        profit.setRemark("");
        profit.setOrderSn(order.getOrderSn());
        profit.setBonusRatio(rate);
        profit.setBonusType(bonusType);
        profit.setBonusTeamId(bonusVo.getAgentId());
        profit.setBonusTeamName(bonusVo.getAgentName());

//        profit.setPayer(bonusVo.getKefuName());
//        profit.setPayerRole(COMPANY);
//        profit.setPayerId(bonusVo.getKefuId());
        // 如果只有一级分红关系
        if (IsEnableEnum.DISABLE.getValue().equals(bonusVo.getIsLv2enable())) {
            // 分红发放人
            profit.setPayer(bonusVo.getObligor1stName());
            profit.setPayerRole(bonusVo.getObligorRole1st());
            profit.setPayerId(bonusVo.getObligor1st());
            profit.setNeedReceive(getBonusProfit(order.getOrderPrice(), rete1));
        } else {
            // 如果存在两级分红关系
            // 两级分红关系情况下，两级分红发放人都是客服，取二级分红关系发放人
            profit.setPayer(bonusVo.getObligor2ndName());
            profit.setPayerId(bonusVo.getObligor2nd());
            profit.setPayerRole(bonusVo.getObligorRole2nd());
            Integer role1 = bonusVo.getObligorRole1st();
            if (GlobalConstant.BONUS_LEVEL1 == bonusType) {
//                profit.setPayer(bonusVo.getObligor1stName());
//                profit.setPayerRole(bonusVo.getObligorRole1st());
//                profit.setPayerId(bonusVo.getObligor1st());
//                profit.setNeedReceive(getBonusProfit(order.getOrderPrice(), rate));
                profit.setNeedReceive(getBonusProfit(order.getOrderPrice(), rate));
                profit.setRemark("经销商（" + bonusVo.getObligor1stName() + "）将业绩团队（"+bonusVo.getAgentName()+"）产生的业绩给（" + bonusVo.getObligee1st()+"）的一级分红由客服（" + bonusVo.getObligor2ndName()+"）发放");
            } else {
//                profit.setPayer(bonusVo.getObligor2ndName());
//                profit.setPayerId(bonusVo.getObligor2nd());
//                profit.setPayerRole(bonusVo.getObligorRole2nd());
                if (AGENT == role1.intValue()) {
                    profit.setNeedReceive(getBonusProfit(order.getOrderPrice(), rete1));
                    // 需上交
                    profit.setReceivor(bonusVo.getObligee1st());
                    profit.setReceivorRole(GlobalConstant.RECEIVORROLE_AGENT);
                    profit.setNeedUppay(getBonusProfit(order.getOrderPrice(), rate));
                    profit.setReceivorId(bonusVo.getObligeeId1st());
                } else {
                    profit.setNeedReceive(getBonusProfit(order.getOrderPrice(), rate));
                }
                // 需上交
            }
        }

        // 上交款
        return profit;
    }


    private int getBelongType(long orderAgentId, long curAgentId) {
        int belong = GlobalConstant.PROFIT_BELONG_TYPE_OWN;
        if (orderAgentId == curAgentId) {
            belong = GlobalConstant.PROFIT_BELONG_TYPE_OWN;
        } else if (orderAgentId != curAgentId) {
            belong = GlobalConstant.PROFIT_BELONG_TYPE_GROUP;
        }
        return belong;
    }


    private int getProfitType(int orderFrom) {
        int profitType = GlobalConstant.PROFIT_TYPE_REBATE;
        if (OrderFromEnum.MEMBER.getValue().intValue() == orderFrom) {
            profitType = GlobalConstant.PROFIT_TYPE_REBATE;
        } else if (OrderFromEnum.AGENT.getValue().intValue() == orderFrom) {
            profitType = GlobalConstant.PROFIT_TYPE_COMM;
        }
        return profitType;
    }


    private int getInfoCode(List<AgentRpcVo> treeList) {
        int sum = 0;
        for (AgentRpcVo vo : treeList) {
            AgentLevelEnum iEnum = EnumUtil.getIEnum(AgentLevelEnum.class, vo.getAgentLevel());
            sum = sum | iEnum.getCode();
        }
        return sum;
    }

    /**
     * 计算代理活动折扣
     * 代理自身折扣 * 活动折扣系数
     *
     * @param actAgentDiscount   活动折扣
     * @param agentDiscount      代理自身折扣
     * @return 活动折扣
     */
    public static BigDecimal calcDisCount(AgentDiscountVo actAgentDiscount, BigDecimal agentDiscount) {
        return NumberUtil.mul(actAgentDiscount.getFactor(), agentDiscount);
    }

    public static BigDecimal calcDisCount(AgentDiscountVo actAgentDiscount, int level, int type) {
        AgentLevelEnum agentLevel = EnumUtil.getIEnum(AgentLevelEnum.class, level);

        BigDecimal disCount = null;
        switch (agentLevel) {
            case DEALER:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getDistributorGold();
                } else {
                    disCount = actAgentDiscount.getDistributorSilver();
                }
                break;
            case LEVEL_1:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getFirstLevelGold();
                } else {
                    disCount = actAgentDiscount.getFirstLevelSilver();
                }
                break;
            case LEVEL_2:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getSecondLevelGold();
                } else {
                    disCount = actAgentDiscount.getSecondLevelSilver();
                }
                break;
            case LEVEL_3:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getThirdLevelGold();
                } else {
                    disCount = actAgentDiscount.getThirdLevelSilver();
                }
                break;
        }
        return disCount;
    }

    private BigDecimal calcDisCount(AgentRebateRuleInfoVo rebateRuleInfo, int level, int type) {
        AgentLevelEnum agentLevel = EnumUtil.getIEnum(AgentLevelEnum.class, level);

        BigDecimal disCount = null;
        switch (agentLevel) {
            case DEALER:
                disCount = rebateRuleInfo.getAgentLevel1();
                break;
            case LEVEL_1:
                disCount = rebateRuleInfo.getAgentLevel2();
                break;
            case LEVEL_2:
                disCount = rebateRuleInfo.getAgentLevel3();
                break;
            case LEVEL_3:
                disCount = rebateRuleInfo.getAgentLevel4();
                break;
            case LEVEL_4:
                disCount = rebateRuleInfo.getAgentLevel5();
                break;
            case LEVEL_5:
                disCount = rebateRuleInfo.getAgentLevel6();
                break;
        }
        return disCount;
    }


    private BigDecimal calcSumDiscount(AgentRebateRuleInfoVo agentRebateRuleInfo) {
        BigDecimal[] disArr = new BigDecimal[6];
        disArr[0] = agentRebateRuleInfo.getAgentLevel1();
        disArr[1] = agentRebateRuleInfo.getAgentLevel2();
        disArr[2] = agentRebateRuleInfo.getAgentLevel3();
        disArr[3] = agentRebateRuleInfo.getAgentLevel4();
        disArr[4] = agentRebateRuleInfo.getAgentLevel5();
        disArr[5] = agentRebateRuleInfo.getAgentLevel6();
        return NumberUtil.add(disArr);
    }


    private Map<String, Object> calcUpAndReceive(Order order,
                                                 AgentRpcVo agent,
                                                 List<AgentRpcVo> treeList,
                                                 AgentDiscountVo agentDiscountVo,
                                                 ActRpcVo actVo
        ) {
        Map<String, Object> result = Maps.newHashMap();
        BigDecimal orderPrice = order.getOrderPrice();
        Long agentId = order.getAgentId();
        int size = treeList.size();
        int index = getCalcProfitPo(agent, treeList);
        // 需收款
        BigDecimal ownReceive = BigDecimal.ZERO;
        // 上交款
        BigDecimal ownUpPay = BigDecimal.ZERO;
        // 上交人角色
        Integer payerRole = null;
        // 上交人id
        Long payerId = null;
        // 上交人
        String payer = "";
        // 收款人id
        Long receivorId = null;
        // 收款人
        String receivor = "";
        // 收款人角色
        Integer receivorRole = null;
        if (agentId.longValue() == agent.getId().longValue()) {
            // 代理商活动个人需收款： 零售价 * 需收款折扣
            if (null != actVo  && ActTypeEnum.ACT_AGENT.getValue().equals(actVo.getActIntegerType())){
                ownReceive = NumberUtil.mul(orderPrice,actVo.getNeedReceiveRate()) ;
            }else{
                ownReceive = orderPrice;
            }
            payerRole = OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom()) ? GlobalConstant.PAYERROLE_MEMBER : GlobalConstant.PAYERROLE_AGENT;
            payerId = order.getBuyerId();
            payer = order.getBuyer();
        } else {
            // 获取直接下级
            AgentRpcVo prePo = treeList.get(index - 1);
//            ownReceive = MoneyUtil.mul(orderPrice, null == agentDiscountVo ? prePo.getDiscount() : calcDisCount(agentDiscountVo, prePo.getAgentLevel(), prePo.getAgentType()));
            ownReceive = MoneyUtil.mul(orderPrice, null == agentDiscountVo ? prePo.getDiscount() : calcDisCount(agentDiscountVo, prePo.getDiscount()));
            payerRole = GlobalConstant.PAYERROLE_AGENT;
            payerId = prePo.getId();
            payer = prePo.getAgentName();
        }
        if (index + 1 < size) {
            receivorId = treeList.get(index + 1).getId();
            receivorRole = GlobalConstant.RECEIVORROLE_AGENT;
            receivor = treeList.get(index + 1).getAgentName();
        } else {
            receivorId = agent.getCustomerId();
            receivor = agent.getCustomerName();
            receivorRole = GlobalConstant.RECEIVORROLE_KEFU;
        }
//        ownUpPay = MoneyUtil.mul(orderPrice, null == agentDiscountVo ? agent.getDiscount() : calcDisCount(agentDiscountVo, agent.getAgentLevel(), agent.getAgentType()));
        ownUpPay = MoneyUtil.mul(orderPrice, null == agentDiscountVo ? agent.getDiscount() : calcDisCount(agentDiscountVo, agent.getDiscount()));
        result.put("needReceive", ownReceive);
        result.put("needUppay", ownUpPay);
        result.put("payerRole", payerRole);
        result.put("payerId", payerId);
        result.put("receivorId", receivorId);
        result.put("receivorRole", receivorRole);
        result.put("payer", payer);
        result.put("receivor", receivor);
        return result;
    }

    private int getCalcProfitPo(AgentRpcVo agent, List<AgentRpcVo> treeList) {
        int index = -1;
        int lenth = treeList.size();
        for (int i = 0; i < lenth; i++) {
            AgentRpcVo calcProfitPo = treeList.get(i);
            long aId = calcProfitPo.getId();
            // 计算出当前登录的代理商
            if (agent.getId().longValue() == aId) {
                index = i;
                break;
            }
        }
        return index;
    }

    /**
     * 解析出父级id
     * @param agentId
     * @param treePath
     * @return
     */
    private CalcProfitPo parseParent(Long agentId, String treePath) {
        CalcProfitPo parentPo = null;
        // 解析订单代理认领树
        List<CalcProfitPo> calcProfitPos = OrderUtil.parseTreePath(treePath);
        CalcProfitPo own = null;
        int ownTreePath = -1;
        int length = calcProfitPos.size();
        for (int i = 0; i < length; i++) {
            CalcProfitPo calcProfitPo = calcProfitPos.get(i);
            long aId = calcProfitPo.getAgentId();
            // 计算出当前登录的代理商
            if (null == own && agentId == aId) {
                own = calcProfitPo;
                ownTreePath = i;
            }
        }

        int afterAgentIndex = ownTreePath + 1;
        if (afterAgentIndex <= length - 1) {
            parentPo = calcProfitPos.get(afterAgentIndex);
        }
        return parentPo;
    }
}
